package org.wattdepot.simulation.uhcampus.main;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import it.sauronsoftware.cron4j.Task;
import it.sauronsoftware.cron4j.TaskExecutionContext;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.simulation.uhcampus.building.BuildingLoad;
import org.wattdepot.simulation.uhcampus.building.BuildingPV;
import org.wattdepot.simulation.util.SimulationClient;

/**
 * Implements the UH Campus simulation task that runs every 20 minutes.  
 * @author Philip Johnson
 */
public class SimulationTask extends Task {

  /** The WattDepotClient for this simulation. */ 
  private WattDepotClient client = null;
  
  /**
   * Initializes the simulation task by reading in the properties from the properties file
   * and creating the WattDepot client.
   */
  public SimulationTask () {
    System.out.println("Getting simulation properties and initializing the WattDepot client.");
    this.client = SimulationClient.getWattDepotClient();
    
    System.out.println("Validating Building sources and getting energy generated/consumed.");
    for (BuildingLoad load : BuildingLoad.values()) {
      load.initializeEnergyConsumed(this.client);
    }
    for (BuildingPV pv : BuildingPV.values()) {
      pv.initializeEnergyGenerated(this.client);
    }

  }

  /**
   * The task that executes every 20 minutes to generate building data. 
   * @param context Ignored. 
   * @throws RuntimeException If problems occur. 
   */
  @Override
  public void execute(TaskExecutionContext context) throws RuntimeException {
    System.out.println("UH Campus simulation waking up at: " + new Date());
    GregorianCalendar now = new GregorianCalendar();
    int interval = this.getCurrentInterval(now);
    
    for (BuildingLoad load : BuildingLoad.values()) {
      load.update(interval);
      load.sendData(this.client);
    }
    for (BuildingPV pv : BuildingPV.values()) {
      pv.update(interval);
      pv.sendData(this.client);
    }
  }
  
  /**
   * Returns an integer between 0 and 71 indicating the current 20 minute interval associated
   * with the passed timestamp.
   * @param today The timestamp of interest. 
   * @return An integer between 0 and 71.
   */
  private int getCurrentInterval(GregorianCalendar today) {
    int hourOfDay = today.get(Calendar.HOUR_OF_DAY);
    int minuteOfDay = today.get(Calendar.MINUTE);
    return (hourOfDay * 3) + (minuteOfDay / 20);
  }
  

}
